# 请设计一个多层感知机(mlp)网络。
#
# 1.该网络执行如下操作：
# - 将输入32×32
# 的图像拉伸为1×1024;
# - 将拉伸后的数据传入第一个隐藏层，该隐藏层为全连接层，包含2048个隐藏单元，并使用Sigmoid激活函数;
# - 将第一个隐藏层的输出传入第二个隐藏层，第二个隐藏层为全连接层，包含512个隐藏单元，使用ReLU激活函数;
# - 将第二个隐藏层的输出传入最后一层，最后一层也为全连接层，输出20维特征，不使用激活函数。
#
# 2.该网络的全连接层权重初始化方案为：全连接层权重服从[0, 1]
# 区间上的均匀分布(uniform);全连接层偏差为常值0.



# 导入需要的torch及相关库
import torch
from torch import nn
import torch.nn.functional as F


# 打印每一层大小信息函数 print_layer_info()
def print_layer_info(net, X):
    for layer in net:
        X = layer(X)
        print(layer.__class__.__name__, 'output shape: \t', X.shape)
        if type(layer) == nn.Linear:
            print('\t', layer.__class__.__name__, 'weight\'s mean: \t', torch.mean(layer.weight[0][0].data))
            print('\t', layer.__class__.__name__, 'bias\'s mean: \t', torch.mean(layer.bias[0].data))


# 你设计的网络,网络名为net
net = nn.Sequential(
    # 将输入32×32的图像拉伸为1×1024将拉伸后的数据传入第一个隐藏层，该隐藏层为全连接层，包含2048个隐藏单元，并使用Sigmoid激活函数;
    nn.Flatten(),
    nn.Linear(in_features=1024, out_features=2048),
    nn.Sigmoid(),
    # 将第一个隐藏层的输出传入第二个隐藏层，第二个隐藏层为全连接层，包含512个隐藏单元，使用ReLU激活函数
    nn.Linear(in_features=2048, out_features=512),
    nn.ReLU(),
    # 将第二个隐藏层的输出传入最后一层，最后一层也为全连接层，输出20维特征，不使用激活函数
    nn.Linear(in_features=512, out_features=20)
)
# 在这里按要求将网络权重初始化
for layer in net:
    if isinstance(layer, nn.Linear):
        nn.init.uniform_(layer.weight, 0, 1)
        nn.init.constant_(layer.bias, 0)

# 测试网络net是否按要求定义
X = torch.rand(size=(1, 1, 32, 32), dtype=torch.float32)
print_layer_info(net, X)

#
# # 代码块的输出需与下面结果保持一致：
# """
# Flatten output shape: 	 torch.Size([1, 1024])
# Linear output shape: 	 torch.Size([1, 2048])
# 	 Linear weight's mean: 	 tensor(0.8631)
# 	 Linear bias's mean: 	 tensor(0.)
# Sigmoid output shape: 	 torch.Size([1, 2048])
# Linear output shape: 	 torch.Size([1, 512])
# 	 Linear weight's mean: 	 tensor(0.0675)
# 	 Linear bias's mean: 	 tensor(0.)
# ReLU output shape: 	 torch.Size([1, 512])
# Linear output shape: 	 torch.Size([1, 20])
# 	 Linear weight's mean: 	 tensor(0.2539)
# 	 Linear bias's mean: 	 tensor(0.)
# """